package com.koko.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koko.admin.dto.*;
import com.koko.admin.entity.Admin;
import com.koko.constant.AccountStateConstant;
import com.koko.constant.DefaultDataConstant;
import com.koko.constant.MessageConstant;
import com.koko.context.AdminContext;
import com.koko.context.BaseContext;
import com.koko.exception.*;
import com.koko.mapper.AdminMapper;
import com.koko.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public Admin login(AdminLoginDTO adminLoginDTO) {
        // 1. 对密码进行md5加密
        String password = adminLoginDTO.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        // 2. 根据提交的用户名查询数据库
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getUsername, adminLoginDTO.getUsername());
        Admin admin = this.getOne(queryWrapper);
        // 3. 处理各种异常
        if (admin == null) {
            // 账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        if (!password.equals(admin.getPassword())) {
            // 密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        if (admin.getState() == AccountStateConstant.DISABLE) {
            // 账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);

        }
        // 4. 返回实体对象
        return admin;
    }

    @Override
    public Admin getAdminInfo(Long adminId) {
        // 1.查找用户
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getId, adminId);
        Admin admin = this.getOne(queryWrapper);
        // 2. 处理异常
        if (admin == null) {
            // 账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        return admin;
    }

    @Override
    public void updateAdminInfo(AdminDTO adminDTO) {
        // 1. 查找用户
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getId, adminDTO.getId());
        Admin admin = this.getOne(queryWrapper);
        // 2. 如果找到用户，则更新用户信息
        if (admin != null) {
            admin.setName(adminDTO.getName());
            admin.setUsername(adminDTO.getUsername());
            admin.setPhone(adminDTO.getPhone());
            admin.setIdNumber(adminDTO.getIdNumber());
            admin.setAvatar(adminDTO.getAvatar());
            admin.setStatus(adminDTO.getStatus());
            // 3. 使用MyBatis-Plus的update方法更新数据库
            this.updateById(admin);
        } else {
            // 4. 如果用户不存在，可以抛出异常或进行其他处理
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
    }

    /**
     * 更新密码
     * @param passwordUpdateDTO
     */
    @Override
    public void updatePassword(PasswordUpdateDTO passwordUpdateDTO) {
        // 1. 对密码进行md5加密
        String oldPwd = passwordUpdateDTO.getOldPwd();
        oldPwd = DigestUtils.md5DigestAsHex(oldPwd.getBytes());
        // 2. 对比新密码和确认密码
        if (passwordUpdateDTO.getNewPwd().equals(passwordUpdateDTO.getRePwd())) {
            // 3. 查找用户密码
            LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Admin::getId, BaseContext.getCurrentId());
            queryWrapper.select(Admin::getPassword);
            Admin admin = this.getOne(queryWrapper);
            // 4. 对比老密码是否正确
            if (admin.getPassword().equals(oldPwd)) {
                // 5. 对新密码进行md5加密
                String newPwd = passwordUpdateDTO.getNewPwd();
                newPwd = DigestUtils.md5DigestAsHex(newPwd.getBytes());
                // 6. 更新密码
                LambdaUpdateWrapper<Admin> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(Admin::getId, BaseContext.getCurrentId());
                updateWrapper.set(Admin::getPassword, newPwd);
                this.update(updateWrapper);
            } else {
                throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
            }
        } else {
            throw new PasswordErrorException(MessageConstant.PASSWORD_NOT_MATCH);
        }
    }

    /**
     * 更新头像
     * @param imageName
     */
    @Override
    public void updateAvatar(String imageName, Long id) {
        try {
            LambdaUpdateWrapper<Admin> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Admin::getId, id);
            updateWrapper.set(Admin::getAvatar, imageName);
            this.update(updateWrapper);
        } catch (Exception e) {
            throw new BaseException(MessageConstant.UNKNOWN_ERROR);
        }

    }

    /**
     * 分页查询
     * @param pageParamsDTO
     * @return
     */
    @Override
    public Page<Admin> pageQuery(PageParamsDTO pageParamsDTO) {
        // 1. 条件构造器
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        // 2. 参数非空判断
        if (pageParamsDTO.getUsernameOrName() != null && !pageParamsDTO.getUsernameOrName().isEmpty()) {
            queryWrapper.and(wrapper ->
                    wrapper.like(Admin::getUsername, pageParamsDTO.getUsernameOrName())
                            .or()
                            .like(Admin::getName, pageParamsDTO.getUsernameOrName())
            );
        }
        if (pageParamsDTO.getState() != null) {
            queryWrapper.eq(Admin::getState, pageParamsDTO.getState());
        }
        // 3. 排序
        queryWrapper.orderByDesc(Admin::getUpdateTime);
        // 4. 获取分页内容
        Page<Admin> pageConfig = new Page<>(pageParamsDTO.getPage(), pageParamsDTO.getPageSize());
        Page<Admin> adminPage = this.page(pageConfig, queryWrapper);
        return adminPage;
    }

    /**
     * 更改管理员状态
     * @param id
     */
    @Override
    public void changeState(Long id) {
        // 1. 查看当前管理员权限
        adminPermission();
        // 2. 修改操作
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getId, id);
        Admin admin = this.getOne(queryWrapper);
        if ( admin != null) {
            LambdaUpdateWrapper<Admin> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Admin::getId, id);
            Boolean newState = !admin.getState();
            updateWrapper.set(Admin::getState, newState);
            this.update(updateWrapper);
        } else {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
    }

    /**
     * 更新管理员
     * @param adminDTO
     */
    @Override
    public void updateAdmin(AdminDTO adminDTO) {
        // 1. 查看当前管理员权限
        adminPermission();
        // 2.1. 查找用户
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getId, adminDTO.getId());
        Admin admin = this.getOne(queryWrapper);
        // 2.2. 如果找到用户，则更新用户信息
        if (admin != null) {
            admin.setName(adminDTO.getName());
            admin.setUsername(adminDTO.getUsername());
            admin.setPhone(adminDTO.getPhone());
            admin.setIdNumber(adminDTO.getIdNumber());
            admin.setAvatar(adminDTO.getAvatar());
            admin.setStatus(adminDTO.getStatus());
            admin.setState(adminDTO.getState());
            // 2.3. 使用MyBatis-Plus的update方法更新数据库
            this.updateById(admin);
        } else {
            // 2.4. 如果用户不存在，可以抛出异常或进行其他处理
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
    }

    /**
     * 添加管理员
     * @param adminDTO
     */
    @Override
    public void addAdmin(AdminDTO adminDTO) {
        // 1. 校验管理员权限
        adminPermission();
        // 2. 封装数据
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminDTO, admin);
        admin.setPassword(DigestUtils.md5DigestAsHex(DefaultDataConstant.DEFAULT_PASSWORD.getBytes()));
        // 3. 处理异常
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getId, admin.getId());
        if (adminMapper.exists(queryWrapper)) {
            // 用户已存在
            throw new AccountAlredyExistException(MessageConstant.ACCOUNT_ALREADY_EXIST);
        }
        // 4. 添加管理员
        this.save(admin);
    }

    /**
     * 当前管理员权限判断
     * @return
     */
    private Boolean adminPermission() {
        Integer permission = AdminContext.getCurrentStatus();
        if (permission != 0) {
            throw new AccountPermissionInsufficientException(MessageConstant.PERMISSION_INSUFFICIENT);
        }
        return true;
    }
}
